﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace CLEX.Service.DataContracts
{
    [DataContract]
    public class TableData
    {
        private static readonly IEqualityComparer<TableData> valueComparer = new TableDataValueComparer();
        [DataMember]
        private readonly string catalog;
        [DataMember]
        private readonly string schema;
        [DataMember]
        private readonly string name;
        [DataMember]
        private readonly List<ColumnData> columns;
        private ReadOnlyCollection<ColumnData> columnsReadOnly;

        public static IEqualityComparer<TableData> ValueComparer
        {
            get { return TableData.valueComparer; }
        } 

        public string Catalog
        {
            get { return catalog; }
        }

        public string Schema
        {
            get { return schema; }
        }

        public string Name
        {
            get { return name; }
        } 

        public ReadOnlyCollection<ColumnData> Columns
        {
            get
            {
                if (columnsReadOnly == null)
                {
                    columnsReadOnly = new ReadOnlyCollection<ColumnData>(columns);
                }
                return columnsReadOnly; 
            }
        }

        private TableData()
        {

        }

        public TableData(string catalog, string schema, string name, IEnumerable<ColumnData> columns)
        {
            this.catalog = catalog;
            this.schema = schema;
            this.name = name;
            this.columns = columns.ToList();
        }

        public override string ToString()
        {
            string v = "[";
            for (int i = 0; i < Columns.Count; i++)
            {
                if (i != 0)
                {
                    v += ", ";
                }
                v += Columns[i].ToString();
            }
            v += "]";
            return string.Format("Catalog: {0}, Schema: {1}, Name: {2}, Columns: {3}", Catalog, Schema, Name, v);
        }

        private sealed class TableDataValueComparer : IEqualityComparer<TableData>
        {
            public bool Equals(TableData x, TableData y)
            {
                if (Object.ReferenceEquals(x, y))
                {
                    return true;
                }
                if (Object.ReferenceEquals(x, null))
                {
                    return false;
                }
                if (Object.ReferenceEquals(y, null))
                {
                    return false;
                }

                return x.catalog == y.catalog && x.schema == y.schema && x.name == y.name && x.columns.SequenceEqual(y.columns, ColumnData.ValueComparer);
            }

            public int GetHashCode(TableData obj)
            {
                if (obj == null)
                {
                    return 0;
                }
                else
                {
                    int hash = obj.catalog.GetHashCode() ^ obj.schema.GetHashCode() ^ obj.name.GetHashCode();
                    foreach (ColumnData column in obj.columns)
                    {
                        hash ^= ColumnData.ValueComparer.GetHashCode(column);
                    }
                    return hash;
                }
            }
        }
    }
}
